{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 工厂模式（Factory Pattern）\n",
    "简单工厂模式、工厂方法模式、抽象工厂模式。\n",
    "\n",
    "- [漫画：设计模式之 “工厂模式”](https://mp.weixin.qq.com/s/qWSI18VJZCg08emqRXXVoQ)\n",
    "- [漫画：什么是 “抽象工厂模式” ？](https://mp.weixin.qq.com/s?__biz=MzIxMjE5MTE1Nw==&mid=2653212055&idx=1&sn=2308694d9aafa1f053d7f2e7d7d7fbf3&chksm=8c99bf4dbbee365bc05d4c746a044f46c31cd50a642ee96768061c4f308afdd9402934f2147b&mpshare=1&scene=24&srcid=0920AwQMGUaNC5r5GGMNjzex&sharer_sharetime=1600612425875&sharer_shareid=941bf38d96956aa7a2147ce2bab1279e#rd)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 简单工厂模式"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "假设我们的业务代码当中，有一个被广泛引用的“口罩类”，这个类实例需要在许多地方被创建和初始化，而初始化的代码也比较复杂。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-26T14:12+0000",
     "start_time": "2020-09-26T14:11:59.453Z"
    }
   },
   "outputs": [],
   "source": [
    "public class Mask {\n",
    "    //构造函数\n",
    "    public Mask(){\n",
    "        // .....\n",
    "        // 100行初始化代码\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "针对这种情况，我们可以构建一个“口罩工厂”专门负责创建口罩对象，把口罩的初始化代码迁移到工厂类的创建方法当中："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-26T14:12+0000",
     "start_time": "2020-09-26T14:12:22.024Z"
    }
   },
   "outputs": [],
   "source": [
    "public class MaskFactory {\n",
    "\n",
    "    public Mask createMask() {\n",
    "        Mask mask = new Mask();\n",
    "        // .....\n",
    "        // 100行初始化代码\n",
    "        return mask;\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "假设口罩类只是一个抽象接口，有两个子类“高端口罩”和“低端口罩”分别实现了这个接口："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-26T14:13+0000",
     "start_time": "2020-09-26T14:13:58.650Z"
    }
   },
   "outputs": [],
   "source": [
    "public interface IMask {\n",
    "    void show();\n",
    "}\n",
    "\n",
    "public class HighEndMask implements IMask {\n",
    "    @Override\n",
    "    public void show() {\n",
    "        System.out.println(\"我是高端口罩\");\n",
    "    }\n",
    "}\n",
    "\n",
    "public class LowEndMask implements IMask {\n",
    "    @Override\n",
    "    public void show(){\n",
    "        System.out.println(\"我的低端口罩\");\n",
    "    }\n",
    "    \n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-26T14:15+0000",
     "start_time": "2020-09-26T14:15:15.113Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "我是高端口罩\n",
      "我的低端口罩\n"
     ]
    }
   ],
   "source": [
    "HighEndMask hem = new HighEndMask();\n",
    "hem.show();\n",
    "\n",
    "LowEndMask lem = new LowEndMask();\n",
    "lem.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "那么口罩工厂该如何创建这两种类型的口罩呢？\n",
    "\n",
    "很简单，在创建方法中传入参数（这里的参数是type），根据参数来做条件判断，决定创建什么样的口罩："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-26T14:16+0000",
     "start_time": "2020-09-26T14:16:27.698Z"
    }
   },
   "outputs": [],
   "source": [
    "public class MaskFactory{\n",
    "\n",
    "    public IMask createMask(String type) {\n",
    "        IMask mask = null;\n",
    "        if(\"高端口罩\".equals(type)){\n",
    "            mask = new HighEndMask();\n",
    "            // .....\n",
    "            // HighEndMask的100行初始化代码\n",
    "        }else if(\"低端口罩\".equals(type)){\n",
    "            mask =  new LowEndMask();\n",
    "            // .....\n",
    "            // LowEndMask的100行初始化代码\n",
    "        }\n",
    "        return mask;\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在客户端，想要创建什么样的口罩对象，只需传入对应的类型名称："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-26T14:20+0000",
     "start_time": "2020-09-26T14:20:53.487Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "我是高端口罩\n",
      "我的低端口罩\n"
     ]
    }
   ],
   "source": [
    "MaskFactory factory = new MaskFactory();\n",
    "IMask maskA = factory.createMask(\"高端口罩\");\n",
    "IMask maskB = factory.createMask(\"低端口罩\");\n",
    "maskA.show();\n",
    "maskB.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过工厂类创建对象，并且根据传入参数决定具体子类对象的做法，就是**简单工厂模式（Simple-Factory-Pattern）**\n",
    "\n",
    "（注：所谓面向对象的开放-封闭原则，就是在程序中对“扩展”开放，对“修改”封闭。如果每次业务改动都要增加新的if-else，就涉及对旧有代码的修改，不但容易出错，可读性也不好。）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 工厂方法模式"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "为每一个口罩类创建对应的工厂子类，这些工厂子类分别实现抽象的工厂接口。\n",
    "\n",
    "这样一来，只要实例化不同的工厂子类，调用创建方法，得到的就是对应的口罩对象。这背后是对象的**多态**特性。\n",
    "\n",
    "根据这个思路，重构一下工厂类的逻辑："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-26T14:31+0000",
     "start_time": "2020-09-26T14:31:06.175Z"
    }
   },
   "outputs": [],
   "source": [
    "public interface IMaskFactory {\n",
    "    IMask createMask();\n",
    "}\n",
    "\n",
    "public class HighEndFactory implements IMaskFactory{\n",
    "\n",
    "    @Override\n",
    "    public IMask createMask() {\n",
    "        IMask mask =  new HighEndMask();\n",
    "        // .....\n",
    "        // HighEndMask的100行初始化代码\n",
    "        return mask;\n",
    "    }\n",
    "}\n",
    "\n",
    "public class LowEndFactory implements IMaskFactory{\n",
    "\n",
    "    @Override\n",
    "    public IMask createMask() {\n",
    "        IMask mask =  new LowEndMask();\n",
    "        // .....\n",
    "        //  LowEndMask的100行初始化代码\n",
    "        return mask;\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在代码中，工厂类变成了抽象的接口，高端口罩工厂和低端口罩工厂这两个子类分别实现了该接口。\n",
    "\n",
    "在客户端，想要创建什么样的口罩对象，只需实例化不同的工厂子类，调用相同的创建方法，无需再传入参数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-26T14:32+0000",
     "start_time": "2020-09-26T14:32:08.249Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "我的低端口罩\n",
      "我是高端口罩\n"
     ]
    }
   ],
   "source": [
    "IMaskFactory factoryA = new LowEndFactory();\n",
    "IMaskFactory factoryB = new HighEndFactory();\n",
    "IMask maskA = factoryA.createMask();\n",
    "IMask maskB = factoryB.createMask();\n",
    "maskA.show();\n",
    "maskB.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "每一个口罩子类都对应一个工厂子类，利用多态特性动态创建对象的模式，就是**工厂方法模式（Factory-Method-Pattern）**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 抽象工厂模式"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "首先看一下产品类的代码，口罩和防护服是两个抽象接口，分别拥有高端和低端两个实现类："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-26T14:42+0000",
     "start_time": "2020-09-26T14:42:24.283Z"
    }
   },
   "outputs": [],
   "source": [
    "public interface IMask {\n",
    "    void showMask();\n",
    "}\n",
    "\n",
    "public class LowEndMask implements IMask {\n",
    "    @Override\n",
    "    public void showMask(){\n",
    "        System.out.println(\"我的低端口罩\");\n",
    "    }\n",
    "}\n",
    "\n",
    "public class HighEndMask implements IMask {\n",
    "    @Override\n",
    "    public void showMask() {\n",
    "        System.out.println(\"我是高端口罩\");\n",
    "    }\n",
    "}\n",
    "\n",
    "public interface IProtectiveSuit {\n",
    "    void showSuit();\n",
    "}\n",
    "\n",
    "public class LowEndProtectiveSuit implements IProtectiveSuit {\n",
    "    @Override\n",
    "    public void showSuit() {\n",
    "        System.out.println(\"我是低端防护服\");\n",
    "    }\n",
    "}\n",
    "\n",
    "public class HighEndProtectiveSuit implements IProtectiveSuit {\n",
    "    @Override\n",
    "    public void showSuit() {\n",
    "        System.out.println(\"我是高端防护服\");\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来是工厂类，由于产品分成了高端和低端两大组，工厂也相应分成了高端工厂和低端工厂，各自负责组内产品的创建："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-26T14:43+0000",
     "start_time": "2020-09-26T14:43:36.569Z"
    }
   },
   "outputs": [],
   "source": [
    "public interface IFactory {\n",
    "    //创建口罩\n",
    "    IMask createMask();\n",
    "    //创建防护服\n",
    "    IProtectiveSuit createSuit();\n",
    "}\n",
    "\n",
    "public class LowEndFactory implements IFactory {\n",
    "    @Override\n",
    "    public IMask createMask() {\n",
    "        IMask mask =  new LowEndMask();\n",
    "        // .....\n",
    "        //  LowEndMask的100行初始化代码\n",
    "        return mask;\n",
    "    }\n",
    "\n",
    "    @Override\n",
    "    public IProtectiveSuit createSuit() {\n",
    "        IProtectiveSuit suit =  new LowEndProtectiveSuit();\n",
    "        // .....\n",
    "        //  LowEndProtectiveSuit的100行初始化代码\n",
    "        return suit;\n",
    "    }\n",
    "}\n",
    "\n",
    "public class HighEndFactory implements IFactory {\n",
    "    @Override\n",
    "    public IMask createMask() {\n",
    "        IMask mask =  new HighEndMask();\n",
    "        // .....\n",
    "        // HighEndMask的100行初始化代码\n",
    "        return mask;\n",
    "    }\n",
    "\n",
    "    @Override\n",
    "    public IProtectiveSuit createSuit() {\n",
    "        IProtectiveSuit suit =  new HighEndProtectiveSuit();\n",
    "        // .....\n",
    "        //  HighEndProtectiveSuit的100行初始化代码\n",
    "        return suit;\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "最后是客户端代码，通过实例化不同的工厂子类，调用不同的创建方法，可以创建出不同的产品："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-26T14:44+0000",
     "start_time": "2020-09-26T14:43:59.879Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "我的低端口罩\n",
      "我是高端口罩\n",
      "我是低端防护服\n",
      "我是高端防护服\n"
     ]
    }
   ],
   "source": [
    "IFactory factoryA = new LowEndFactory();\n",
    "IFactory factoryB = new HighEndFactory();\n",
    "//创建低端口罩\n",
    "IMask maskA = factoryA.createMask();\n",
    "//创建高端口罩\n",
    "IMask maskB = factoryB.createMask();\n",
    "//创建低端防护服\n",
    "IProtectiveSuit suitA = factoryA.createSuit();\n",
    "//创建高端防护服\n",
    "IProtectiveSuit suitB = factoryB.createSuit();\n",
    "\n",
    "maskA.showMask();\n",
    "maskB.showMask();\n",
    "suitA.showSuit();\n",
    "suitB.showSuit();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "像这样把产品分组，组内不同产品对应于同一工厂类不用方法的设计模式，就是**抽象工厂模式（Abstract Factory Pattern）**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 总结"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-26T14:48+0000",
     "start_time": "2020-09-26T14:48:13.120Z"
    }
   },
   "source": [
    "**简单工厂模式：**\n",
    "\n",
    "简单工厂模式有唯一的工厂类，工厂类的创建方法根据传入的参数做if-else条件判断，决定最终创建什么样的产品对象。\n",
    "\n",
    "**工厂方法模式：**\n",
    "\n",
    "工厂方法模式由多个工厂类实现工厂接口，利用多态来创建不同的产品对象，从而避免了冗长的if-else条件判断。\n",
    "\n",
    "**抽象工厂模式：**\n",
    "\n",
    "抽象工厂模式把产品子类进行分组，同组中的不同产品由同一个工厂子类的不同方法负责创建，从而减少了工厂子类的数量。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-26T14:49+0000",
     "start_time": "2020-09-26T14:49:20.433Z"
    }
   },
   "source": [
    "# 应用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "熟悉spring框架的小伙伴，一定知道spring的一个重要特性：**依赖注入（DI）**。\n",
    "\n",
    "通过spring的依赖注入，开发人员不需要在业务代码中手动实例化bean对象，也不需要知道任何工厂类。\n",
    "\n",
    "bean对象从创建到销毁的整个过程，完全交给spring容器来管理，用户需要做的仅仅是在xml配置文件中（或使用注解）设置bean的各项属性："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-26T14:53+0000",
     "start_time": "2020-09-26T14:53:29.881Z"
    }
   },
   "source": [
    "```xml\n",
    "<bean id=\"userController\" class=\"com.xiaohui.controller.UserController\">\n",
    "    <constructor-arg name=\"userService\" ref=\"userService\"></constructor-arg>\n",
    "</bean>\n",
    "\n",
    "<bean id=\"userService\" class=\"com.xiaohui.service.UserService\">\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "根据上面的配置，spring容器会动态创建UserController对象，并创建UserController所依赖的UserService对象。\n",
    "\n",
    "如果开发人员希望把userService这个bean对象的实现类换成另一个类，并不需要改动任何代码，只需要修改配置文件中对应bean的class属性即可。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在大多数情况下，我们使用new关键字创建对象，对象所属的class是在代码中明确定义好的。\n",
    "\n",
    "但是在少数情况下，我们需要借助class的元信息（比如完整类名），在程序运行期间动态创建对象，这就用到了Java的**反射**。\n",
    "\n",
    "当我们在spring配置文件中配置了相应的bean，启动项目，spring会为我们解析xml配置文件，并根据bean的不同生命周期，由spring内部的“工厂”创建出bean对象。\n",
    "\n",
    "对spring依赖注入原理有兴趣的小伙伴，可以阅读spring源码中的**BeanFactory**接口，以及相关的实现类。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Java",
   "language": "java",
   "name": "java"
  },
  "language_info": {
   "codemirror_mode": "java",
   "file_extension": ".jshell",
   "mimetype": "text/x-java-source",
   "name": "Java",
   "pygments_lexer": "java",
   "version": "11.0.8+10-post-Ubuntu-0ubuntu120.04"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "306.875px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
